﻿namespace Iesi.Collections.Generic
{
    using Iesi.Collections;
    using System;
    using System.Collections;
    using System.Collections.Generic;

    [Serializable]
    public sealed class ImmutableSet<T> : Set<T>
    {
        private const string ERROR_MESSAGE = "Object is immutable.";
        private ISet<T> mBasisSet;

        public ImmutableSet(ISet<T> basisSet)
        {
            this.mBasisSet = basisSet;
        }

        public sealed override bool Add(T o)
        {
            throw new NotSupportedException("Object is immutable.");
        }

        public sealed override bool AddAll(ICollection<T> c)
        {
            throw new NotSupportedException("Object is immutable.");
        }

        public sealed override void Clear()
        {
            throw new NotSupportedException("Object is immutable.");
        }

        public sealed override object Clone()
        {
            return new ImmutableSet<T>(this.mBasisSet);
        }

        public sealed override bool Contains(T o)
        {
            return this.mBasisSet.Contains(o);
        }

        public sealed override bool ContainsAll(ICollection<T> c)
        {
            return this.mBasisSet.ContainsAll(c);
        }

        public sealed override void CopyTo(T[] array, int index)
        {
            this.mBasisSet.CopyTo(array, index);
        }

        public sealed override ISet<T> ExclusiveOr(ISet<T> a)
        {
            return new ImmutableSet<T>(this.GetUltimateBasisSet().ExclusiveOr(a));
        }

        public sealed override IEnumerator<T> GetEnumerator()
        {
            return this.mBasisSet.GetEnumerator();
        }

        private ISet<T> GetUltimateBasisSet()
        {
            ISet<T> mBasisSet = this.mBasisSet;
            while (mBasisSet is ImmutableSet<T>)
            {
                mBasisSet = ((ImmutableSet<T>) mBasisSet).mBasisSet;
            }
            return mBasisSet;
        }

        public sealed override ISet<T> Intersect(ISet<T> a)
        {
            return new ImmutableSet<T>(this.GetUltimateBasisSet().Intersect(a));
        }

        public sealed override ISet<T> Minus(ISet<T> a)
        {
            return new ImmutableSet<T>(this.GetUltimateBasisSet().Minus(a));
        }

        protected override void NonGenericCopyTo(Array array, int index)
        {
            ((ICollection) this.BasisSet).CopyTo(array, index);
        }

        protected sealed override ISet NonGenericExclusiveOr(ISet a)
        {
            return new ImmutableSet(((ISet) this.GetUltimateBasisSet()).ExclusiveOr(a));
        }

        protected sealed override ISet NonGenericIntersect(ISet a)
        {
            return new ImmutableSet(((ISet) this.GetUltimateBasisSet()).Intersect(a));
        }

        protected sealed override ISet NonGenericMinus(ISet a)
        {
            return new ImmutableSet(((ISet) this.GetUltimateBasisSet()).Minus(a));
        }

        protected sealed override ISet NonGenericUnion(ISet a)
        {
            return new ImmutableSet(((ISet) this.GetUltimateBasisSet()).Union(a));
        }

        public sealed override bool Remove(T o)
        {
            throw new NotSupportedException("Object is immutable.");
        }

        public sealed override bool RemoveAll(ICollection<T> c)
        {
            throw new NotSupportedException("Object is immutable.");
        }

        public sealed override bool RetainAll(ICollection<T> c)
        {
            throw new NotSupportedException("Object is immutable.");
        }

        public sealed override ISet<T> Union(ISet<T> a)
        {
            return new ImmutableSet<T>(this.GetUltimateBasisSet().Union(a));
        }

        internal ISet<T> BasisSet
        {
            get
            {
                return this.mBasisSet;
            }
        }

        public sealed override int Count
        {
            get
            {
                return this.mBasisSet.Count;
            }
        }

        public sealed override bool IsEmpty
        {
            get
            {
                return this.mBasisSet.IsEmpty;
            }
        }

        public sealed override bool IsReadOnly
        {
            get
            {
                return true;
            }
        }

        public sealed override bool IsSynchronized
        {
            get
            {
                return ((ICollection) this.mBasisSet).IsSynchronized;
            }
        }

        public sealed override object SyncRoot
        {
            get
            {
                return ((ICollection) this.mBasisSet).SyncRoot;
            }
        }
    }
}

